package com.atguigu.edu.realtime.utils;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.edu.realtime.common.Constant;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.flink.shaded.guava18.com.google.common.base.CaseFormat;

import java.lang.reflect.InvocationTargetException;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class JdbcUtil {

    public static Connection getPhoenixConnection() {
        String driver = Constant.PHOENIX_DRIVER;
        String url = Constant.PHOENIX_URL;
        return getJdbcConnection(driver, url, null, null);
    }

    private static Connection getJdbcConnection(String driver, String url, String user, String password) {
        try {
            Class.forName(driver);
        } catch (ClassNotFoundException e) {
            // 如果 driver 加载失败, 则程序没有必须继续运行
            throw new RuntimeException(e);
        }
        try {
            return DriverManager.getConnection(url, user, password);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    public static void closeConnection(Connection conn) throws SQLException {
        if (conn != null && !conn.isClosed())  {
            conn.close();
        }
    }

    public static Connection getMysqlConnection() {
        String driver = Constant.MYSQL_DRIVER;
        String url = Constant.MYSQL_URL;
        String user = Constant.MYSQL_USER;
        String password = Constant.MYSQL_PASSWORD;
        return getJdbcConnection(driver, url, user, password);
    }
    //

    /**
     * 使用指定的连接对象, 执行一个 sql 语句
     * 如果使用泛型, 则内部必定会用反射方式去创建对象,
     * @param conn jdbc 连接
     * @param querySql  查询语句
     * @param args sql 的占位符的对应的值
     * @param tClass
     * @return 查询的结果
     * TODO
     */
    public static <T> List<T> queryList(Connection conn, String querySql, Object[] args, Class<T> tClass, boolean isUnderlineToCamel) throws SQLException, InstantiationException, IllegalAccessException, InvocationTargetException {
        List<T> result = new ArrayList<>();
        // 1. 获取一个预处理语句
        PreparedStatement ps = conn.prepareStatement(querySql);
        // 2. 给 sql 中的占位符赋值
        for (int i = 0; args != null && i < args.length; i++) {
            Object arg = args[i];
            ps.setObject(i + 1, arg);
        }
        // 3. 执行 sql 语句
        ResultSet resultSet = ps.executeQuery();
        ResultSetMetaData metaData = resultSet.getMetaData();  // 获取表的元数据: 比如列名, 列的数量, 列的类型 ...
        // 4. 把结果使用 List 集合进行封装
        // 把结果集中的每一行全部遍历出来(List 集合中), 然后再把每一列遍历(放入到一个 T 类型的对象中)
        while (resultSet.next()) {
            T t = tClass.newInstance();  // 创建一个 T 类型的对象, 使用的是无参构造器
            // T对象中, 有可能会多个属性, 每个属性对应一列
            for (int i = 1; i <= metaData.getColumnCount(); i++) {
                // 获取列名: 从元数据获取. 对应着 T 中的属性名
                // 获取列的值: 从resultSet
                String name = metaData.getColumnLabel(i);
                if (isUnderlineToCamel) {
                    // 小驼 LOWER_CAMEL: 方法名, 属性名, 变量名  首字母小写, 其他单词的首字母大小   myName
                    // 大驼 UPPER_CAMEL: 类名, 接口名  所有单词的首字母大写   MyName
                    name = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, name);
                }
                Object value = resultSet.getObject(i);
                //t.name=value
                BeanUtils.setProperty(t,name,value);
            }
            result.add(t);
        }
        // 5. 关闭预处理语句
        return result;
    }

    public static void main(String[] args) throws SQLException, InvocationTargetException, InstantiationException, IllegalAccessException {
//        List<TableProcess> list = queryList(getMysqlConnection(), "select * from table_process", null, TableProcess.class, true);
//        List<JSONObject> list = queryList(getMysqlConnection(), "select * from gmall2022.user_info", null, JSONObject.class, true);
        List<JSONObject> list = queryList(getPhoenixConnection(), "select * from dim_sku_info", null, JSONObject.class, true);
        for (Object tp : list) {

            System.out.println(tp);
        }
    }
}
